package com.codefish.codefishseckill.config;


import com.codefish.codefishseckill.config.properties.IgnoreUrlProperties;
import com.codefish.codefishseckill.security.CustomerAuthenticationFilter;
import com.codefish.codefishseckill.security.JwtTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;

import javax.annotation.Resource;


/**
 * 安全相关配置类
 *
 * @author codefish
 * @version 1.0
 * @date 2022/07/27 下午 05:22
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableConfigurationProperties({IgnoreUrlProperties.class})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    UserDetailsService userDetailServiceImpl;
    @Autowired
    PasswordEncoder myPasswordEncoder;
    @Autowired
    AuthenticationSuccessHandler myAuthenticationSuccessHandler;
    @Autowired
    AuthenticationFailureHandler myAuthenticationFailureHandler;
    @Autowired
    LogoutHandler myLogoutHandler;
    @Autowired
    AuthenticationEntryPoint myUnLoginHandler;
    @Autowired
    JwtTokenFilter jwtTokenFilter;
    @Autowired
    IgnoreUrlProperties ignoreUrlProperties;
    @Autowired
    CustomerAuthenticationFilter customerAuthenticationFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailServiceImpl).passwordEncoder(myPasswordEncoder);
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //配置url拦截规则
        //url放行
        for (String url : ignoreUrlProperties.getIgnoreUrl()) {
            http.authorizeRequests().antMatchers(url).permitAll();
        }


        http.authorizeRequests()
                //其它url需要验证身份
                .anyRequest().authenticated()
                //配置自定义拒绝处理
                .and().exceptionHandling()
                //无权限异常处理交由ExceptionController来进行全局异常处理
//                .accessDeniedHandler(accessDeniedHandler)
                //配置未登录异常处理器
                .authenticationEntryPoint(myUnLoginHandler)
                //禁用csrf
                .and().csrf().disable()
                //不使用session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                //登录处理
                .and().formLogin()
                .loginPage("/login")
                .permitAll().and()
                //自定义权限拦截器
                .addFilterAt(customerAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class)
                //配置登出处理
                .logout().logoutUrl("/form/logout").addLogoutHandler(myLogoutHandler);
    }

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
}
